package com.yanqu.road.server.gameplayer.module.activity.drink;

import com.alibaba.fastjson.JSON;
import com.yanqu.road.entity.activity.ActivityInfo;
import com.yanqu.road.entity.activity.drink.DrinkBlock;
import com.yanqu.road.entity.activity.drink.DrinkEliminateResult;
import com.yanqu.road.entity.activity.drink.DrinkEliminateRoundResult;
import com.yanqu.road.entity.activity.drink.DrinkEliminateStageResult;
import com.yanqu.road.entity.activity.drink.DrinkOrder;
import com.yanqu.road.entity.activity.drink.DrinkUserData;
import com.yanqu.road.entity.activity.drink.config.DrinkConfig;
import com.yanqu.road.entity.config.goods.GoodsInfo;
import com.yanqu.road.entity.enums.eGamePlayerEventType;
import com.yanqu.road.entity.enums.eLogMoneyType;
import com.yanqu.road.entity.enums.eMailType;
import com.yanqu.road.entity.enums.eSystemId;
import com.yanqu.road.entity.log.LogDrinkEliminate1;
import com.yanqu.road.entity.log.LogDrinkEliminate2;
import com.yanqu.road.entity.log.LogDrinkEnergy;
import com.yanqu.road.entity.log.LogDrinkOrder;
import com.yanqu.road.logic.bussiness.activity.DrinkActivityBusiness;
import com.yanqu.road.logic.helper.CalcPowerResult;
import com.yanqu.road.logic.helper.PowerHelper;
import com.yanqu.road.pb.activity.DrinkActivityProto;
import com.yanqu.road.server.gameplayer.GamePlayer;
import com.yanqu.road.server.gameplayer.module.base.GeneralModule;
import com.yanqu.road.server.gameplayer.module.player.CurrencyModule;
import com.yanqu.road.server.logic.mail.MailManager;
import com.yanqu.road.server.manger.MultipleLanguageMgr;
import com.yanqu.road.server.manger.activity.ActivityMgr;
import com.yanqu.road.server.manger.activity.drink.DrinkEliminateLogic;
import com.yanqu.road.server.manger.activity.drink.DrinkMgr;
import com.yanqu.road.server.manger.config.GoodsMgr;
import com.yanqu.road.server.manger.config.SystemOpenMgr;
import com.yanqu.road.server.manger.log.AutoLogMgr;
import com.yanqu.road.server.manger.log.LogMgr;
import com.yanqu.road.server.pb.DrinkPb;
import com.yanqu.road.server.protocol.ClientProtocol;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.utils.property.Property;
import com.yanqu.road.utils.property.PropertyHelper;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;

public class DrinkModule extends GeneralModule {

    private DrinkUserData userData;

    public DrinkModule(GamePlayer player) {
        super(player);
    }

    @Override
    public boolean loadData() {
        DrinkConfig drinkConfig = DrinkMgr.getDrinkConfig();
        if (drinkConfig != null && ActivityMgr.activityInShowTime(drinkConfig.getActivityInfo())) {
            userData = DrinkActivityBusiness.getDrinkUserData(drinkConfig.getActivityInfo().getActivityId(), getUserId());
        }
        return true;
    }

    @Override
    public boolean afterLoadData() {
        return true;
    }

    @Override
    public boolean saveData() {
        if (userData != null) {
            if (userData.isInsertOption()) {
                DrinkActivityBusiness.addDrinkUserData(userData);
            } else if (userData.isUpdateOption()) {
                DrinkActivityBusiness.updateDrinkUserData(userData);
            }
        }
        return true;
    }

    @Override
    public void afterLogin() {
        syncConfig();
        initUserData();
        syncUserData();
    }

    /**
     * 初始化玩家数据
     */
    public synchronized void initUserData() {
        // 系统未解锁
        if (!SystemOpenMgr.systemOpen(player, eSystemId.DrinkActivity.getValue())) {
            return;
        }

        // 没有活动
        DrinkConfig drinkConfig = DrinkMgr.getDrinkConfig();
        if (drinkConfig == null || !ActivityMgr.activityInShowTime(drinkConfig.getActivityInfo())) {
            return;
        }

        ActivityInfo activityInfo = drinkConfig.getActivityInfo();

        // 已经有数据了
        if (userData != null && userData.getActivityId() == activityInfo.getActivityId()) {
            return;
        }

        DrinkUserData tmpUserData = new DrinkUserData();
        tmpUserData.setActivityId(activityInfo.getActivityId());
        tmpUserData.setUserId(getUserId());
        tmpUserData.setScore(0);
        tmpUserData.setEnergy(drinkConfig.getMaxEnergy());
        tmpUserData.setLastRecTime(System.currentTimeMillis());
        tmpUserData.setGuideIndex(0);

        // 单倍格子
        int guideIndex = tmpUserData.getGuideIndex();
        int[] initBlock = drinkConfig.getInitBlock();
        int[][] blockList1 = new int[DrinkEliminateLogic.MAX_HEIGHT][DrinkEliminateLogic.MAX_WIDTH];
        for (int y = 0; y < blockList1.length; y++) {
            for (int x = 0; x < blockList1[y].length; x++) {
                blockList1[y][x] = initBlock[guideIndex++];
            }
        }
        tmpUserData.setBlockList(blockList1, 1);
        tmpUserData.setGuideIndex(guideIndex);

        // 八倍格子
        int index = 0;
        int[] initBlockMulti = drinkConfig.getInitBlockMulti();
        int[][] blockList4 = new int[DrinkEliminateLogic.MAX_HEIGHT][DrinkEliminateLogic.MAX_WIDTH];
        for (int y = 0; y < blockList4.length; y++) {
            for (int x = 0; x < blockList4[y].length; x++) {
                blockList4[y][x] = initBlockMulti[index++];
            }
        }
        tmpUserData.setBlockList(blockList4, 8);

        tmpUserData.setOrder(DrinkMgr.createOrder(drinkConfig.getGuideOrderId()), 1);
        tmpUserData.setOrder(DrinkMgr.createOrder(DrinkMgr.getRandomOrderId(8)), 8);
        tmpUserData.setWaitRewardOrderList(new ArrayList<>(), 1);
        tmpUserData.setWaitRewardOrderList(new ArrayList<>(), 8);

        DrinkMgr.checkOrderIdList(tmpUserData.getOrderIdList(1), 1);
        DrinkMgr.checkOrderIdList(tmpUserData.getOrderIdList(8), 8);

        // 十六倍新增数据
        if (drinkConfig.getFastUnlockVipLevel() != Integer.MAX_VALUE) {
            tmpUserData.setOrder(DrinkMgr.createOrder(DrinkMgr.getRandomOrderId(16)), 16);
            tmpUserData.setWaitRewardOrderList(new ArrayList<>(), 16);
            DrinkMgr.checkOrderIdList(tmpUserData.getOrderIdList(16), 16);
            index = 0;
            int[] initBlockFast = drinkConfig.getInitBlockFast();
            int[][] blockList16 = new int[DrinkEliminateLogic.MAX_HEIGHT][DrinkEliminateLogic.MAX_WIDTH];
            for (int y = 0; y < blockList16.length; y++) {
                for (int x = 0; x < blockList16[y].length; x++) {
                    blockList16[y][x] = initBlockFast[index++];
                }
            }
            tmpUserData.setBlockList(blockList16, 16);
        }

        tmpUserData.setInsertOption();
        userData = tmpUserData;
    }

    /**
     * 同步配置
     */
    public void syncConfig() {
        DrinkConfig drinkConfig = DrinkMgr.getDrinkConfig();
        if (drinkConfig == null || !ActivityMgr.activityInShowTime(drinkConfig.getActivityInfo())) {
            return;
        }

        DrinkActivityProto.DrinkSyncConfigRespMsg.Builder builder = DrinkPb.parseDrinkSyncConfigRespMsg(drinkConfig, player.getLanguage());
        player.sendPacket(ClientProtocol.U_DRINK_SYNC_CONFIG, builder);
    }

    /**
     * 同步玩家数据
     */
    public void syncUserData() {
        DrinkConfig drinkConfig = DrinkMgr.getDrinkConfig();
        if (drinkConfig == null || !ActivityMgr.activityInShowTime(drinkConfig.getActivityInfo())) {
            return;
        }
        DrinkUserData data = getUserData();
        if (data == null) {
            return;
        }

        DrinkActivityProto.DrinkSyncUserDataRespMsg.Builder builder = DrinkActivityProto.DrinkSyncUserDataRespMsg.newBuilder();
        builder.setEnergy(data.getEnergy());
        builder.setLastRecTime(data.getLastRecTime());
        player.sendPacket(ClientProtocol.U_DRINK_SYNC_USER_DATA, builder);
    }

    /**
     * 获取玩家数据
     */
    public DrinkUserData getUserData() {

        // 检查体力恢复
        DrinkConfig drinkConfig = DrinkMgr.getDrinkConfig();
        if (userData != null && drinkConfig != null) {

            int logBeforeEnergy = userData.getEnergy();

            CalcPowerResult result = PowerHelper.calcPower(
                    userData.getLastRecTime() / 1000,
                    drinkConfig.getEnergyRecTime() / 1000,
                    drinkConfig.getEnergyRecCount(),
                    drinkConfig.getMaxEnergy(),
                    userData.getEnergy());
            userData.setEnergy(result.getCurPower());
            userData.setLastRecTime(result.getLastRecoverTime() * 1000);

            // 日志
            if (userData.getEnergy() != logBeforeEnergy) {
                AutoLogMgr.add(new LogDrinkEnergy(userData.getUserId(), userData.getActivityId(), 2, userData.getEnergy() - logBeforeEnergy, userData.getEnergy()));
            }
        }

        return userData;
    }

    /**
     * 使用体力药
     */
    public int useEnergyItem(int count) {

        if (count <= 0 || count > 99999) {
            return GameErrorCode.E_DRINK_ACTIVITY_USE_COUNT_ERROR;
        }

        DrinkConfig drinkConfig = DrinkMgr.getDrinkConfig();
        Property cost = new Property();
        cost.addProperty(drinkConfig.getEnergyRecItemId(), BigInteger.valueOf(count));

        // 计算恢复数量
        GoodsInfo goodsInfo = GoodsMgr.getGoodsById(drinkConfig.getEnergyRecItemId());
        BigInteger energyCount = goodsInfo.getParamList().get(0);
        int totalCount = energyCount.intValue() * count;

        // 扣道具
        if (!player.getModule(CurrencyModule.class).removeCurrency(cost, eLogMoneyType.DrinkActivity, eLogMoneyType.DrinkUseEnergyItemCost)) {
            return GameErrorCode.E_DRINK_ACTIVITY_ITEM_NO_ENOUGH;
        }

        // 加体力
        userData.setEnergy(userData.getEnergy() + totalCount);
        if (userData.getEnergy() > drinkConfig.getMaxEnergy()) {
            userData.setLastRecTime(System.currentTimeMillis());
        }

        DrinkActivityProto.DrinkUseEnergyItemRespMsg.Builder builder = DrinkActivityProto.DrinkUseEnergyItemRespMsg.newBuilder();
        builder.setRet(0);
        builder.setEnergy(userData.getEnergy());
        builder.setLastRecTime(userData.getLastRecTime());
        player.sendPacket(ClientProtocol.U_DRINK_USE_ENERGY_ITEM, builder);

        // 日志
        AutoLogMgr.add(new LogDrinkEnergy(userData.getUserId(), userData.getActivityId(), 3, totalCount, userData.getEnergy()));
        return 0;
    }

    /**
     * 扣体力
     */
    public boolean reduceEnergy(int count) {
        if (userData.getEnergy() < count)
            return false;

        DrinkConfig drinkConfig = DrinkMgr.getDrinkConfig();
        int maxEnergy = drinkConfig.getMaxEnergy();
        boolean aboveMaxBefore = userData.getEnergy() >= maxEnergy;

        userData.setEnergy(userData.getEnergy() - count);
        if (aboveMaxBefore)
            userData.setLastRecTime(System.currentTimeMillis());

        // 日志
        AutoLogMgr.add(new LogDrinkEnergy(userData.getUserId(), userData.getActivityId(), 1, count, userData.getEnergy()));
        return true;
    }

    /**
     * 领取订单奖励
     */
    public int getOrderReward() {
        List<DrinkOrder> orderList1 = userData.getWaitRewardOrderList(1);
        List<DrinkOrder> orderList4 = userData.getWaitRewardOrderList(8);
        List<DrinkOrder> orderList16 = userData.getWaitRewardOrderList(16);
        if (orderList1.isEmpty() && orderList4.isEmpty() && orderList16.isEmpty())
            return GameErrorCode.E_DRINK_ACTIVITY_NO_ORDER_CAN_REWARD;

        List<Integer> orderIdList = new ArrayList<>();
        List<String> rewardList = new ArrayList<>();
        Property property = new Property();

        for (DrinkOrder drinkOrder : orderList1) {
            orderIdList.add(drinkOrder.getoId());
            rewardList.add(drinkOrder.getReward());
            property.addProperty(PropertyHelper.parseStringToProperty(drinkOrder.getReward()));
        }
        for (DrinkOrder drinkOrder : orderList4) {
            orderIdList.add(drinkOrder.getoId());
            rewardList.add(drinkOrder.getReward());
            property.addProperty(PropertyHelper.parseStringToProperty(drinkOrder.getReward()));
        }
        for (DrinkOrder drinkOrder : orderList16) {
            orderIdList.add(drinkOrder.getoId());
            rewardList.add(drinkOrder.getReward());
            property.addProperty(PropertyHelper.parseStringToProperty(drinkOrder.getReward()));
        }

        // 积分奖励需要再处理
        long score = property.getCountByGoodsId(DrinkMgr.getDrinkConfig().getScoreItemId()).longValue();

        // 清空列表
        userData.setWaitRewardOrderList(new ArrayList<>(), 1);
        userData.setWaitRewardOrderList(new ArrayList<>(), 8);
        userData.setWaitRewardOrderList(new ArrayList<>(), 16);

        // 加奖励
        player.getModule(CurrencyModule.class).addCurrency(property, eLogMoneyType.DrinkActivity, eLogMoneyType.DrinkGetOrderReward);

        // 加积分
        userData.setScore(userData.getScore() + score);
        // 榜单
        player.notifyListener(eGamePlayerEventType.DrinkActivityScoreRank.getValue(), userData.getScore());
        player.notifyListener(eGamePlayerEventType.DrinkActivityCrossScoreRank.getValue(), userData.getScore());

        DrinkActivityProto.DrinkGetOrderRewardRespMsg.Builder builder = DrinkActivityProto.DrinkGetOrderRewardRespMsg.newBuilder();
        builder.setRet(0);
        builder.addAllOrderIdList(orderIdList);
        builder.addAllRewardList(rewardList);
        player.sendPacket(ClientProtocol.U_DRINK_GET_ORDER_REWARD, builder);
        return 0;
    }

    /**
     * 消除
     */
    public int eliminateBlock(int fromX, int fromY, int toX, int toY, int multi) {

        DrinkConfig drinkConfig = DrinkMgr.getDrinkConfig();
        List<Integer> costEnergyList = drinkConfig.getCostEnergyList();
        int costEnergy = 1;
        if (multi == 1) costEnergy = costEnergyList.get(0);
        else if (multi == 8) costEnergy = costEnergyList.get(1);
        else if (multi == 16) costEnergy = costEnergyList.get(2);

        // 体力
        if (userData.getEnergy() < costEnergy) {
            return GameErrorCode.E_DRINK_ACTIVITY_ENERGY_NO_ENOUGH;
        }

        // 消除
        DrinkEliminateResult result = DrinkEliminateLogic.eliminateBlock(userData, multi, fromX, fromY, toX, toY);
        if (result.getRet() != 0) {
            return result.getRet();
        }

        DrinkActivityProto.DrinkEliminateRespMsg.Builder builder = DrinkActivityProto.DrinkEliminateRespMsg.newBuilder();
        builder.setRet(result.getRet());

        // 处理结果
        long totalScore = 0;
        List<DrinkOrder> finishOrderList = new ArrayList<>();
        for (DrinkEliminateRoundResult roundResult : result.getRoundResultList()) {
            DrinkActivityProto.DrinkEliminateRoundMsg.Builder roundMsg = DrinkPb.parseDrinkEliminateRoundMsg(roundResult);
            builder.addRoundMsgList(roundMsg);

            for (DrinkEliminateStageResult stageResult : roundResult.getStageResultList()) {
                for (DrinkBlock drinkBlock : stageResult.getBlockList()) {
                    totalScore += drinkBlock.getScore();
                }
            }
            if (roundResult.getFinishOrder() != null) {
                finishOrderList.add(roundResult.getFinishOrder());
            }
        }

        // 组装积分奖励
        int scoreItemId = DrinkMgr.getDrinkConfig().getScoreItemId();
        Property property = new Property();
        property.addProperty(scoreItemId, BigInteger.valueOf(totalScore));

        // 扣体力
        reduceEnergy(costEnergy);

        // 设置结果
        userData.setGuideIndex(result.getGuideIndex());
        userData.setBlockList(DrinkMgr.getCopyBlockList(result.getRoundResultList().get(result.getRoundResultList().size() - 1).getBlockList()), multi);
        userData.setOrder(result.getCurOrder(), multi);
        userData.getWaitRewardOrderList(multi).addAll(finishOrderList);
        userData.setOrderIdList(result.getOrderIdList(), multi);
        userData.setScore(userData.getScore() + totalScore);

        // 加奖励
        player.getModule(CurrencyModule.class).addCurrency(property, eLogMoneyType.DrinkActivity, eLogMoneyType.DrinkEliminateGet);

        // 榜单
        player.notifyListener(eGamePlayerEventType.DrinkActivityScoreRank.getValue(), userData.getScore());
        player.notifyListener(eGamePlayerEventType.DrinkActivityCrossScoreRank.getValue(), userData.getScore());

        // 返回
        builder.setGameData(DrinkPb.parseDrinkGameDataMsg(userData, multi));
        player.sendPacket(ClientProtocol.U_DRINK_ELIMINATE_BLOCK, builder);

        // 消除日志1
        DrinkEliminateRoundResult logRoundResult1 = result.getRoundResultList().get(0);
        Property logBombProp = new Property();
        long logScore = 0;
        int logCount = 0;
        for (DrinkEliminateStageResult stageResult : logRoundResult1.getStageResultList()) {
            for (DrinkBlock drinkBlock : stageResult.getBlockList()) {
                logScore += drinkBlock.getScore();
                logCount++;
                if (DrinkEliminateLogic.isBomb(drinkBlock.getC())) {
                    logBombProp.addProperty(drinkBlock.getC(), BigInteger.ONE);
                }
            }
        }
        AutoLogMgr.add(new LogDrinkEliminate1(
                userData.getUserId(), userData.getActivityId(), multi == 16 ? 2 : multi == 8 ? 1 : 0, PropertyHelper.parsePropertyToString(logBombProp), logCount, logScore
        ));

        // 消除日志2
        List<DrinkEliminateRoundResult> logRoundResultList = result.getRoundResultList();
        if (logRoundResultList.size() > 1) {
            logScore = 0;
            logCount = 0;
            int logMaxCon = 1;
            for (int i = 1; i < logRoundResultList.size(); i++) {
                DrinkEliminateRoundResult logRoundResult2 = logRoundResultList.get(i);
                if (logRoundResult2.getType() != 1) {
                    continue;
                }
                logMaxCon++;
                for (DrinkEliminateStageResult stageResult : logRoundResult2.getStageResultList()) {
                    for (DrinkBlock drinkBlock : stageResult.getBlockList()) {
                        logScore += drinkBlock.getScore();
                        logCount++;
                    }
                }
            }
            AutoLogMgr.add(new LogDrinkEliminate2(
                    userData.getUserId(), userData.getActivityId(), multi == 16 ? 2 : multi == 8 ? 1 : 0, logMaxCon, logCount, logScore
            ));
        }

        // 订单日志
        DrinkEliminateRoundResult lastRound = result.getRoundResultList().get(result.getRoundResultList().size() - 1);
        if (lastRound.getFinishOrder() != null) {
            DrinkOrder finishOrder = lastRound.getFinishOrder();
            AutoLogMgr.add(new LogDrinkOrder(userData.getUserId(), userData.getActivityId(), finishOrder.getoId(), true, finishOrder.getReward()));
        } else if (lastRound.getFailOrder() != null) {
            DrinkOrder failOrder = lastRound.getFailOrder();
            AutoLogMgr.add(new LogDrinkOrder(userData.getUserId(), userData.getActivityId(), failOrder.getoId(), false, failOrder.getReward()));
        }

        return 0;
    }

    /**
     * 自动发订单奖励
     */
    public synchronized void autoOrderReward() {

        // 领奖期
        if (!ActivityMgr.activityInRewardPeriod(DrinkMgr.getActivityInfo())) {
            return;
        }

        // 获取数据
        if (userData == null) return;
        List<DrinkOrder> orderList1 = userData.getWaitRewardOrderList(1);
        List<DrinkOrder> orderList4 = userData.getWaitRewardOrderList(8);
        List<DrinkOrder> orderList16 = userData.getWaitRewardOrderList(16);
        if (orderList1.isEmpty() && orderList4.isEmpty() && orderList16.isEmpty()) {
            return;
        }

        // 获取奖励
        Property property = new Property();
        for (DrinkOrder drinkOrder : orderList1) {
            property.addProperty(PropertyHelper.parseStringToProperty(drinkOrder.getReward()));
        }
        for (DrinkOrder drinkOrder : orderList4) {
            property.addProperty(PropertyHelper.parseStringToProperty(drinkOrder.getReward()));
        }
        for (DrinkOrder drinkOrder : orderList16) {
            property.addProperty(PropertyHelper.parseStringToProperty(drinkOrder.getReward()));
        }

        // 清空列表
        userData.setWaitRewardOrderList(new ArrayList<>(), 1);
        userData.setWaitRewardOrderList(new ArrayList<>(), 8);
        userData.setWaitRewardOrderList(new ArrayList<>(), 16);

        // 邮件发奖
        String mailTitle = MultipleLanguageMgr.getContent(MailManager.DRINK_ORDER_AUTO_REWARD_TITLE, player.getLanguage());
        String mailContent = MultipleLanguageMgr.getContent(MailManager.DRINK_ORDER_AUTO_REWARD_CONTENT, player.getLanguage());
        MailManager.sendMailOnLoad(player, eMailType.SYSTEM.getValue(), PropertyHelper.parsePropertyToString(property), mailContent, mailTitle);
    }

}
